from django.db import transaction
from django.db.models import Value, CharField
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.response import Response
from rest_framework.views import APIView

from apps.projectbases.models import ProjectPlanHModel
from bases.response import APIResponse
from apps.project.DevelopProjectService import DevelopProjectService
from apps.project.MaintainProjectService import MaintainProjectService
from apps.project.ProjectProcessService import ProjectProcessService
from apps.project.filters import ProjectQuotaFilters, ProjectMaintainFilters, ProjectDevelopFilters
from apps.project.models import ProjectQuotaModel, ProjectMaintainModel, ProjectDevelopModel, \
    ProjectMaintainAccountModel, ProjectMaintainStageModel, ProjectDevelopAccountModel, ProjectDevelopStageModel, \
    ProjectProcessModel
from apps.project.serializers import ProjectQuotaSerializer, ProjectDevelopSerializer, \
    ProjectMaintainSerializer, ProjectMaintainAccountSerializer, ProjectMaintainStageSerializer, \
    ProjectDevelopAccountSerializer, ProjectDevelopStageSerializer, ProjectProcessSerializer, \
    ProjectCombineAccountSerializer, ProjectCombineStageSerializer
from bases.response import SuccessResponse
from bases.viewsets import APIModelViewSet
from utils.utils import update_set, update_instance


class ProjectQuotaViewSet(APIModelViewSet):

    def get_queryset(self):
        # 获取当前登录用户
        current_user = self.request.user
        # 获取该用户所属部门
        user_departments = current_user.departments.all()
        if user_departments:
            # 筛选该用户所属部门下的报价单数据
            queryset = ProjectQuotaModel.objects.filter(projectPlanFK__departmentFK__in=user_departments)
        else:
            queryset = ProjectQuotaModel.objects.all()

        return queryset

    serializer_class = ProjectQuotaSerializer
    filter_class = ProjectQuotaFilters

    @transaction.atomic
    @action(methods=['delete'], detail=True)
    def batchDelete(self, request, *args, **kwargs):
        """
        该方法用于批量删除功能，前端返回一个由id构成的数组，后端进行for循环删除
        """
        ids = request.data.get('ids')
        for id in ids:
            query = ProjectQuotaModel.objects.get(pk=id)
            query.delete()

        return SuccessResponse()



class ProjectMaintainViewSet(APIModelViewSet):

    def get_queryset(self):
        # 获取当前登录用户
        current_user = self.request.user
        # 获取该用户所属部门
        user_departments = current_user.departments.all()
        if user_departments:
            # 筛选该用户所属部门下的维护项目数据
            queryset = ProjectMaintainModel.objects.filter(projectPlanFK__departmentFK__in=user_departments)
        else:
            queryset = ProjectMaintainModel.objects.all()
        return queryset

    serializer_class = ProjectMaintainSerializer
    filter_class = ProjectMaintainFilters

    @transaction.atomic
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True) # 借助serializer进行数据校验
        maintainProjectService = MaintainProjectService(request)
        instance = maintainProjectService.createMaintainProjectRequest(serializer.validated_data) # 传递校验后的数据给createMaintainProjectRequest
        serializer = ProjectMaintainSerializer(instance)
        return SuccessResponse(serializer.data)

    @transaction.atomic
    def update(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True) # 借助serializer进行数据校验
        instance = self.get_object()
        maintainProjectService = MaintainProjectService(request)
        result = maintainProjectService.updateMaintainProjectRequest(instance, serializer.validated_data)

        serializer = ProjectMaintainSerializer(result)

        return SuccessResponse(serializer.data)

    @transaction.atomic
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        if instance.project_status != 'O':
            raise ValidationError("只有初始状态的数据才允许被删除")

        maintainProjectService = MaintainProjectService(request)
        maintainProjectService.deleteMaintainProjectRequest(instance)

        return SuccessResponse()

    @transaction.atomic
    @action(methods=['delete'], detail=True)
    def batchDelete(self, request, *args, **kwargs):
        """
        该方法用于批量删除功能，前端返回一个由id构成的数组，后端进行for循环删除
        """
        ids = request.data.get('ids')
        for id in ids:
            query = ProjectMaintainModel.objects.get(pk=id)
            query.delete()

        return SuccessResponse()

    @transaction.atomic
    @action(detail=True, methods=['put'])
    def release(self, request, *args, **kwargs):
        """
        该方法主要用来实现生效功能
        """
        instance = self.get_object()
        if instance.project_status != 'O':
            raise ValidationError('只有初始状态下的数据可以进行确认操作')

        instance.project_status = 'R'
        update_instance(instance, request)

        # 在项目生效时记录进度报告
        processService = ProjectProcessService(request)
        processService.createProjectProcess(instance.project_status, instance)

        instance.save()

        return SuccessResponse()

    @transaction.atomic
    @action(detail=True, methods=['put'])
    def close(self, request, *args, **kwargs):
        instance = self.get_object()
        if instance.project_status != 'R':
            raise ValidationError('只有生效态下的数据可以进行关闭操作')
        instance.project_status = 'C'
        update_instance(instance, request)
        # 在项目关闭时记录进度报告
        processService = ProjectProcessService(request)
        result = processService.createProjectProcess(instance.project_status, instance)

        instance.save()
        return SuccessResponse()

    @transaction.atomic
    @action(detail=True, methods=['put'])
    def SplitUpdate(self, request, *args, **kwargs):
        id = kwargs.get('pk')
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)  # 借助serializer进行数据校验
        maintainProjectService = MaintainProjectService(request)
        instance = maintainProjectService.updateOrigMaintain(id, serializer.validated_data)
        serializer = ProjectMaintainSerializer(instance)

        return SuccessResponse(serializer.data)

class ProjectMaintainInitView(APIView):
    """
    维护项目初始化视图：根据项目ID+报价单ID，按照相应的公式自动计算出其他字段数值，并回传到前端
    """
    def get(self, request):
        projectPlanFK_id = request.GET.get('projectPlanFK')
        quoteFK_id = request.GET.get('quoteFK')

        maintainProjectService = MaintainProjectService(request)
        result = maintainProjectService.initialMaintainProject(projectPlanFK_id, quoteFK_id)

        return SuccessResponse(result)

class ProjectMaintainInitBySalesAmount(APIView):
    """
    维护项目前端修改“预定销售金额”后自动计算其他字段（暂时没有使用）
    """
    def get(self, request):
        sales_amount = request.GET.get('sales_amount')

        maintainProjectService = MaintainProjectService(request)
        result = maintainProjectService.initMaintainBySalesAmount(sales_amount)

        return SuccessResponse(result)

class ProjectDevelopViewSet(APIModelViewSet):
    """
    开发项目视图：增、删、改、生效、关闭
    """
    def get_queryset(self):
        # 获取当前登录用户
        current_user = self.request.user
        # 获取该用户所属部门
        user_departments = current_user.departments.all()
        if user_departments:
            # 筛选该用户所属部门下的开发项目数据
            queryset = ProjectDevelopModel.objects.filter(projectPlanFK__departmentFK__in=user_departments)
        else:
            queryset = ProjectDevelopModel.objects.all()
        return queryset

    serializer_class = ProjectDevelopSerializer
    filter_class = ProjectDevelopFilters

    @transaction.atomic
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True) # 借助serializer进行数据校验
        developProjectService = DevelopProjectService(request)
        instance = developProjectService.createDevelopProjectRequest(serializer.validated_data)
        serializer = ProjectDevelopSerializer(instance)

        return SuccessResponse(serializer.data)

    @transaction.atomic
    def update(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True) # 借助serializer进行数据校验
        instance = self.get_object()
        developProjectService = DevelopProjectService(request)
        result = developProjectService.updateDevelopProjectRequest(instance, serializer.validated_data)

        serializer = ProjectDevelopSerializer(result)

        return SuccessResponse(serializer.data)

    @transaction.atomic
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        if instance.project_status != 'O':
            raise ValidationError("只有初始状态的数据才允许被删除")

        developProjectService = DevelopProjectService(request)
        developProjectService.deleteDevelopProjectRequest(instance)

        return SuccessResponse()

    @transaction.atomic
    @action(methods=['delete'], detail=True)
    def batchDelete(self, request, *args, **kwargs):
        """
        该方法用于批量删除功能，前端返回一个由id构成的数组，后端进行for循环删除
        """
        ids = request.data.get('ids')
        for id in ids:
            query = ProjectDevelopModel.objects.get(pk=id)
            query.delete()

        return SuccessResponse()

    @transaction.atomic
    @action(detail=True, methods=['put'])
    def release(self, request, *args, **kwargs):
        """
        该方法主要用来实现生效功能
        """
        instance = self.get_object()
        if instance.project_status != 'O':
            raise ValidationError('只有初始状态下的数据可以进行确认操作')
        instance.project_status = 'R'
        update_instance(instance, request)
        # 在项目生效时，插入项目进度记录
        processService = ProjectProcessService(request)
        result = processService.createProjectProcess(instance.project_status, instance)

        instance.save()
        return SuccessResponse()

    @transaction.atomic
    @action(detail=True, methods=['put'])
    def close(self, request, *args, **kwargs):
        instance = self.get_object()
        if instance.project_status != 'R':
            raise ValidationError('只有生效态下的数据可以进行关闭操作')
        instance.project_status = 'C'
        update_instance(instance, request)
        # 在项目关闭后，插入项目进度记录
        processService = ProjectProcessService(request)
        result = processService.createProjectProcess(instance.project_status, instance)

        instance.save()
        return SuccessResponse()

    @transaction.atomic
    @action(detail=True, methods=['put'])
    def SplitUpdate(self, request, *args, **kwargs):
        id = kwargs.get('pk')
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)  # 借助serializer进行数据校验
        developProjectService = DevelopProjectService(request)
        instance = developProjectService.updateOrigDevelop(id, serializer.validated_data)
        serializer = ProjectDevelopSerializer(instance)

        return SuccessResponse(serializer.data)

class ProjectDevelopInitView(APIView):
    """
    该视图用于初始化开发项目管理：根据前端传来得项目计划ID与报价单ID自动计算相应数据
    """
    def get(self, request):
        projectPlanFK_id = request.GET.get('projectPlanFK')
        quoteFK_id = request.GET.get('quoteFK')

        developProjectService = DevelopProjectService(request)
        result = developProjectService.initialDevelopProject(projectPlanFK_id, quoteFK_id)

        return SuccessResponse(result)

class ProjectDevlopInitByQuoteDays(APIView):
    """
    该视图通过前端传来得报价天数与报价金额自动计算相关数据（未使用）
    """
    def get(self, request):
        quoted_days = request.GET.get('quoted_days')
        quote_amount = request.GET.get('quote_amount')

        developProjectService = DevelopProjectService(request)
        result = developProjectService.initDevelopByQuoteDays(quoted_days, quote_amount)

        return SuccessResponse(result)

class ProjectMaintainAccountViewSet(APIModelViewSet):
    def get_queryset(self):
        maintain_project = self.request.GET.get('projectMaintainFK')
        if maintain_project:
            queryset = ProjectMaintainAccountModel.objects.filter(projectMaintainFK__id=maintain_project)
        else:
            queryset = ProjectMaintainAccountModel.objects.all()
        return queryset

    serializer_class = ProjectMaintainAccountSerializer


class ProjectMaintainStageViewSet(APIModelViewSet):
    # queryset = ProjectMaintainStageModel.objects.all()
    def get_queryset(self):
        maintain_project = self.request.GET.get('projectMaintainFK')
        if maintain_project:
            queryset = ProjectMaintainStageModel.objects.filter(projectMaintainFK__id=maintain_project)
        else:
            queryset = ProjectMaintainStageModel.objects.all()
        return queryset
    serializer_class = ProjectMaintainStageSerializer


class ProjectDevelopAccountViewSet(APIModelViewSet):
    def get_queryset(self):
        develop_project = self.request.GET.get('projectDevelopFK')
        if develop_project:
            queryset = ProjectDevelopAccountModel.objects.filter(projectDevelopFK__id=develop_project)
        else:
            queryset = ProjectDevelopAccountModel.objects.all()
        return queryset
    serializer_class = ProjectDevelopAccountSerializer


class ProjectDevelopStageViewSet(APIModelViewSet):
    def get_queryset(self):
        develop_project = self.request.GET.get('projectDevelopFK')
        if develop_project:
            queryset = ProjectDevelopStageModel.objects.filter(projectDevelopFK__id=develop_project)
        else:
            queryset = ProjectDevelopStageModel.objects.all()
        return queryset
    serializer_class = ProjectDevelopStageSerializer


class ProjectProcessViewSet(APIModelViewSet):
    queryset = ProjectProcessModel.objects.all()
    serializer_class = ProjectProcessSerializer


class ProjectCombineAccountView(APIView):
    """合并展示维护+开发的项目核算履历的数据"""

    def get(self, request, plan_id):
        # 获取项目计划
        plan = ProjectPlanHModel.objects.get(id=plan_id)

        # 先找到关联的开发项目和维护项目
        develop_projects = plan.develop_projects.all() # 通关反向关联查询数据
        maintain_projects = plan.maintain_projects.all()

        # 再找到关联的财务数据
        develop_account_data = ProjectDevelopAccountModel.objects.filter(projectDevelopFK__in=develop_projects)
        maintain_account_data = ProjectMaintainAccountModel.objects.filter(projectMaintainFK__in=maintain_projects)

        # 序列化并合并数据
        combined_data = []

        for item in develop_account_data:
            serialized = ProjectCombineAccountSerializer(item)
            item_data = serialized.data
            # 添加动态字段
            item_data['model_type'] = 'D'
            item_data['foreign_key_id'] = item.projectDevelopFK_id
            item_data['project_name'] = item.projectDevelopFK.project_name
            combined_data.append(item_data)


        for item in maintain_account_data:
            serialized = ProjectCombineAccountSerializer(item)
            item_data = serialized.data
            item_data['model_type'] = 'M'
            item_data['foreign_key_id'] = item.projectMaintainFK_id
            item_data['project_name'] = item.projectMaintainFK.project_name
            combined_data.append(item_data)

        return SuccessResponse(combined_data)


class ProjectCombineStageView(APIView):
    """合并展示维护+开发项目的阶段别预实管理数据"""

    def get(self, request, plan_id):
        # 获取项目计划
        plan = ProjectPlanHModel.objects.get(id=plan_id)

        # 先找到关联的开发项目和维护项目
        develop_projects = plan.develop_projects.all() # 通关反向关联查询数据
        maintain_projects = plan.maintain_projects.all()

        # 再找到关联的财务数据
        develop_stage_data = ProjectDevelopStageModel.objects.filter(projectDevelopFK__in=develop_projects)
        maintain_stage_data = ProjectMaintainStageModel.objects.filter(projectMaintainFK__in=maintain_projects)

        # 序列化并合并数据
        combined_data = []

        for item in develop_stage_data:
            serialized = ProjectCombineStageSerializer(item)
            item_data = serialized.data
            # 添加动态字段
            item_data['model_type'] = 'D'
            item_data['foreign_key_id'] = item.projectDevelopFK_id
            item_data['project_name'] = item.projectDevelopFK.project_name
            combined_data.append(item_data)


        for item in maintain_stage_data:
            serialized = ProjectCombineStageSerializer(item)
            item_data = serialized.data
            item_data['model_type'] = 'M'
            item_data['foreign_key_id'] = item.projectMaintainFK_id
            item_data['project_name'] = item.projectMaintainFK.project_name
            combined_data.append(item_data)

        return SuccessResponse(combined_data)
